
local MakePlayerCharacter = require "prefabs/player_common"


local assets = {
    Asset("SCRIPT", "scripts/prefabs/player_common.lua"),
}
local prefabs = {}

-- 初始物品
local start_inv = {
	"i26_laotie",
}
-- 当人物复活的时候
local function onbecamehuman(inst)
	-- 设置人物的移速（1表示1倍于wilson）
	inst.components.locomotor:SetExternalSpeedMultiplier(inst, "yunli_speed_mod", 1.2)
	
end
--当人物死亡的时候
local function onbecameghost(inst)
	inst.components.locomotor:SetExternalSpeedMultiplier(inst, "yunli_speed_mod", 1.2)
end

-- 重载游戏或者生成一个玩家的时候
local function onload(inst)
    inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman)
    inst:ListenForEvent("ms_becameghost", onbecameghost)

    if inst:HasTag("playerghost") then
        onbecameghost(inst)
    else
        onbecamehuman(inst)
    end
end



local ljeves = {feetslipped = true,knockback = true,devoured = true,suspended = true,
repelled = true,startled = true,snared = true,attacked = true,mindcontrolled = true,knockedout = true,yawn = true,monkeycursehit = true,}

local function Lisfn1(inst)
    local weapon = inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
    if not weapon or not weapon:HasTag("i26_laotie") 
    then return end
	inst.SoundEmitter:KillSound("i26dd")
    inst.SoundEmitter:PlaySound("i26yl/sfx/i26dd","i26dd", .6)
    --TheNet:Say(1)
end
local function Lisfn2(inst)
    local weapon = inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
    if not weapon or not weapon:HasTag("i26_laotie") 
    then return end
	inst.SoundEmitter:KillSound("i26s3_1")
    inst.SoundEmitter:PlaySound("i26yl/sfx/i26s3_1","i26s3_1", .6)
    --TheNet:Say(2)
end
local function Lisfn22(inst)
    local weapon = inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
    if not weapon or not weapon:HasTag("i26_laotie") 
    then return end
	inst.SoundEmitter:KillSound("i26s3_2")
    inst.SoundEmitter:PlaySound("i26yl/sfx/i26s3_2","i26s3_2", .6)
end
local function Lisfn3(inst)
    local weapon = inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
    if not weapon or not weapon:HasTag("i26_laotie") 
    then return end
	inst.SoundEmitter:KillSound("i26s3_3")
    inst.SoundEmitter:PlaySound("i26yl/sfx/i26s3_3","i26s3_3", .6)

    --TheNet:Say(3)
end

local function h_pinnable(Pinnable)
	local oldStick = Pinnable.Stick
	function Pinnable:Stick(goo_build, splashfxlist, ...)
		if self.inst:HasTag("i26bati") then return end
		return oldStick(self, goo_build, splashfxlist, ...)
	end
end
local function h_freezable(Freezable)
	if not Freezable then return end
	local oldFreeze = Freezable.Freeze
	function Freezable:Freeze(freezetime, ...)
		if self.inst:HasTag("i26bati") then return end 
		return oldFreeze(self, freezetime, ...)
	end
end
local function h_cursable(Cursable)
	if not Cursable then return end
    local old1 = Cursable.IsCursable
    Cursable.IsCursable = function(self, item)
        if item and item.components.curseditem and item.components.curseditem.curse  == "MONKEY" then
            return false
        end
        return old1(self, item)
    end
    local old2 = Cursable.ApplyCurse
    Cursable.ApplyCurse = function(self, item)
        if item and item.components.curseditem and item.components.curseditem.curse  == "MONKEY" then
            item:RemoveTag("applied_curse")
            item.components.curseditem.cursed_target = nil
            return false
        end
        return old2(self, item)
    end
    local old3 = Cursable.ForceOntoOwner
    Cursable.ForceOntoOwner = function(self, item)
        if item and item.components.curseditem and item.components.curseditem.curse  == "MONKEY" then
            return false
        end
        return old3(self, item)
    end
end

local common_postinit = function(inst) 
	-- Minimap icon
	inst.MiniMapEntity:SetIcon( "yunli.tex" )

	inst:AddTag("i26")
	inst:AddTag("i26build1")
	
	inst:AddComponent("i26key")

	inst.components.i26key:AddActionListener("Skill1",
	{Namespace = "i26_rpc",Action = "Skill1"},true)
	inst.components.i26key:AddActionListener("Skill2",
	{Namespace = "i26_rpc",Action = "Skill2"},true)


	inst.i26dd = net_event(inst.GUID, "i26dd")
	inst.i26s3start = net_event(inst.GUID, "i26s3start")
	inst.i26attacked = net_event(inst.GUID, "i26attacked")
	inst.i26s3hit = net_event(inst.GUID, "i26s3hit")

	if not TheWorld.ismastersim  then
		inst:ListenForEvent("i26dd", Lisfn1)
		inst:ListenForEvent("i26s3start", Lisfn2)
		inst:ListenForEvent("i26attacked", Lisfn22)
		inst:ListenForEvent("i26s3hit", Lisfn3)
	end
end


local master_postinit = function(inst)
	-- 人物音效
	inst.soundsname = "willow"

	--最喜欢的食物  名字 倍率（1.2）
	inst.components.foodaffinity:AddFoodtypeAffinity(FOODTYPE.GOODIES, 1.2)

	inst.components.health:SetMaxHealth(TUNING.YUNLI_HEALTH)
	inst.components.hunger:SetMax(TUNING.YUNLI_HUNGER)
	inst.components.sanity:SetMax(TUNING.YUNLI_SANITY)
    inst.components.combat.damagemultiplier = 1
	inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE
	--inst.components.health.externalabsorbmodifiers:SetModifier(inst, .3)
	inst:AddComponent("i26skill")


	local oldgetatk = inst.components.combat.GetAttacked
	inst.components.combat.GetAttacked = function(self, attacker, damage, weapon, stimuli, spdamage, ...)
		if self.inst.components.health and self.inst.components.health:IsDead() then return true end
		self.lastwasattackedtime = GetTime()

		if inst.i26onbattle_task ~= nil then
            inst.i26onbattle_task:Cancel()
            inst.i26onbattle_task = nil
        end
        inst.i26onbattle_task = inst:DoTaskInTime(5, function()
            inst.i26onbattle_task = nil
        end)

		local alldd, newdam, newspd = inst.components.i26skill:GetAtk(attacker, damage, weapon, stimuli, spdamage)
		if alldd then return false end 
		return oldgetatk(self, attacker, newdam, weapon, stimuli, newspd, ...)
	end


	local oldpe = inst.PushEvent
	inst.PushEvent = function(inst, name, data, ...)
		if inst:HasTag("i26bati") and ljeves[name] then return end 
		return oldpe(inst, name, data, ...)
	end

	h_pinnable(inst.components.pinnable)
	inst:ListenForEvent("ms_respawnedfromghost", function()
		inst:DoTaskInTime(.1, function()
			h_freezable(inst.components.freezable)	
		end)
	end)
	h_freezable(inst.components.freezable)
	h_cursable(inst.components.cursable)
	--inst.components.builder.ingredientmod = .5 
	-- 补丁 睡眠情况下r装备老铁，再使用r，老铁会被卸下至0点，尝试hook OnSleepIn、OnWakeUp貌似无效，遂监听
	-- 顺便可以预防其他特殊情况的问题 
	inst:ListenForEvent("unequip", function(_, data)	
		if not data or not data.item then return end 
		data.item:DoTaskInTime(1/30, function(item)
			if not inst or not inst:IsValid() or not item:IsValid() then return end 
			if item:GetDistanceSqToPoint(0, 0, 0) < 4  then
				inst.components.inventory:GiveItem(item, nil, inst:GetPosition())
			end
		end)
	end)

	inst:ListenForEvent("huohuo_buff_triggered", function()
		inst.components.i26skill:DoDelta(1)
	end)
	inst:ListenForEvent("i26xushi", function()
		inst.components.i26skill:DoDelta(1)
	end)

	inst.OnLoad = onload
    inst.OnNewSpawn = onload
	-- inst.OnSleepIn = OnSleepIn
	-- inst.OnWakeUp = OnWakeUp
end

return MakePlayerCharacter("yunli", prefabs, assets, common_postinit, master_postinit, start_inv)
